home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
476-500
/
500
/
wiconify
/
wiconsetter.lzh
/
wIconSetter
/
Source
/
wIconSetter.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-19
|
16KB
|
591 lines
/*
* WICONSETTER A companion utility to wIconify. wIconSetter allows
* you to specify custom icons for windows ans screens
* that normally use the default icons.
*
* wIconSetter.c Main loader code for wIconSetter.
*
* Copyright 1990 by Davide P. Cervone, all rights reserved.
* You may use this code, provided this copyright notice is kept intact.
*/
#include "wIconSetter.h"
static char *program = PROGRAM;
static char *copyright = COPYRIGHT;
static char *handler = HANDLERCODE; /* The name of the handler file */
#define HANDLER &(handler[2]) /* Handler without the L: */
static struct IconHandlerInfo *IconHandlerData;
static long Segment; /* The loaded handler segment */
ICONPROGRAM *FirstProgram; /* The list of icons */
ICONPROGRAM *ProgramAny; /* the program named [ANY] */
ICONDEFINE *FirstDefine; /* the list of defined icons */
/*
* PrefixMatch()
*
* Calls the handler's PrefixMatch routine, after checking
* for NAME_ANY matches.
*/
int PrefixMatch(s1,s2)
char *s1,*s2;
{
if (s1 == NAME_ANY) return(s2 == NAME_ANY); else
if (s2 == NAME_ANY) return(1);
return(VAR(PrefixMatch)(s1,s2));
}
/*
* FreeImage()
*
* If an image structure was given,
* If the image has allocated data, free it
* Free the image structure itself
*/
void FreeImage(theImage)
struct Image *theImage;
{
if (theImage)
{
if (theImage->ImageData) FreeRaster(theImage->ImageData,
theImage->Width,theImage->Height*theImage->Depth);
FREESTRUCT(Image,theImage);
}
}
/*
* FreeWindow()
*
* Free any images associated with the window
* Free the window's icon's name, if any
* Free the window's name, if any
* Free the window structure itself
*/
void FreeWindow(theWindow)
ICONWINDOW *theWindow;
{
if (theWindow->Flags & IW_IMAGE) FreeImage(theWindow->Icon.Image);
if (theWindow->Flags & IW_SELECT) FreeImage(theWindow->Icon.Select);
if (theWindow->Flags & IW_MASK) FreeImage(theWindow->Mask);
if (theWindow->Flags & IW_NAME) FREECHAR(theWindow->Icon.Name);
if (theWindow->Name != NAME_NULL && theWindow->Name != NAME_ANY &&
theWindow->Name != SCREENICON) FREECHAR(theWindow->Name);
FREESTRUCT(IconWindow,theWindow);
}
/*
* FreeScreen()
*
* While the screen has more windows
* Free the window and move on to the next one
* Free the screen's name, if any
* Free the screen structure itself
*/
void FreeScreen(theScreen)
ICONSCREEN *theScreen;
{
ICONWINDOW *nextWindow;
while (theScreen->Window)
{
nextWindow = theScreen->Window->Next;
FreeWindow(theScreen->Window);
theScreen->Window = nextWindow;
}
if (theScreen->Name != NAME_NULL && theScreen->Name != NAME_ANY)
FREECHAR(theScreen->Name);
FREESTRUCT(IconScreen,theScreen);
}
/*
* FreeProgram()
*
* While there are more screens associated with this program
* Free the screen and move on to the next one
* Free the program's name, if any
* Free the program structure itself
*/
void FreeProgram(theProg)
ICONPROGRAM *theProg;
{
ICONSCREEN *nextScreen;
while (theProg->Screen)
{
nextScreen = theProg->Screen->Next;
FreeScreen(theProg->Screen);
theProg->Screen = nextScreen;
}
if (theProg->Name != NAME_NULL && theProg->Name != NAME_ANY)
FREECHAR(theProg->Name);
FREESTRUCT(IconProgram,theProg);
}
/*
* FreeLists()
*
* Convert the binary tree back into a linked list
* While there are programs in the list
* Free the program and move on to the next one
* If there is a ProgramAny, free it
* While there are more definitions in the list
* Free the definition and move on to the next one
*/
static void FreeLists()
{
ICONPROGRAM *nextProg;
ICONDEFINE *nextDefine;
extern ICONPROGRAM *TreeToList();
FirstProgram = TreeToList(FirstProgram);
while (FirstProgram)
{
nextProg = FirstProgram->Next;
FreeProgram(FirstProgram);
FirstProgram = nextProg;
}
if (ProgramAny) FreeProgram(ProgramAny);
while (FirstDefine)
{
nextDefine = FirstDefine->Next;
FreeDefine(FirstDefine);
FirstDefine = nextDefine;
}
}
/*
* DoExit()
*
* General purpose error-exit routine. Print an error message if one was
* supplied (it can have up to three parameters), and then clean up any
* memory, libraries, etc. that need to be handled before exiting.
*/
void DoExit(s,x1,x2,x3)
char *s, *x1, *x2, *x3;
{
long status = EXIT_OK;
if (s != NULL)
{
printf(s,x1,x2,x3);
printf("\n");
status = EXIT_ERROR;
}
FreeLists();
if (Segment) UnLoadSeg(Segment);
if (IntuitionBase) CloseLibrary(IntuitionBase);
if (GfxBase) CloseLibrary(GfxBase);
exit(status);
}
/*
* CheckLibOpen()
*
* Call OpenLibrary() for the specified library, and check that the
* open succeeded.
*/
static void CheckLibOpen(lib,name,rev)
APTR *lib;
char *name;
int rev;
{
extern APTR OpenLibrary();
if ((*lib = OpenLibrary(name,(LONG)rev)) == NULL)
DoExit("Can't open %s",name);
}
/*
* LoadHandler()
*
* Try to LoadSeg the handler from the current directory, and if it is not
* found, try the L: directory. If neither can be loaded, exit with an
* error message. Once the handler is loaded, call the Setup routine
* in the handler code and pass the loader version number. The handler will
* check the version for compatibility and returns NULL if there is a
* mismatch, or a pointer to the shared data if everything is OK.
* Check the handler version number, and then store the loader version
* and the segment list pointer for use in unloading the handler later.
* The MsgPort is the first item in the IconHandlerInfo structure. It is used
* to link the information into the system port list, where we can find it
* later.
*/
void LoadHandler(thePort)
struct MsgPort **thePort;
{
struct IconHandlerInfo *(*Setup)();
if ((Segment = LoadSeg(HANDLER)) == NULL)
if ((Segment = LoadSeg(handler)) == NULL)
DoExit("Can't load %s",handler);
Setup = (struct IconHandlerInfo *(*)()) ((Segment << 2) + 4);
IconHandlerData = (*Setup)(LOADVERS);
if (IconHandlerData)
{
if (var(MajVers) < MINHMAJVERS ||
(var(MajVers) == MINHMAJVERS && var(MinVers) < MINHMINVERS))
DoExit("Version mismatch with %s",HANDLER);
*thePort = &(IconHandlerData->IconPort);
} else {
DoExit("%s reports a version mismatch",HANDLER);
}
var(Segment) = Segment;
}
/*
* SetVectors()
*
* Set the Intuition library vectors for the routines we are trapping
* to the routines specified by the handler. Save the old routine pointers
* for later replacement.
*/
static void SetVectors()
{
VAR(OldOpenWindow) =
SetFunction(IntuitionBase,&LVOOpenWindow,var(aOpenWindow));
VAR(OldSetWindowTitles) =
SetFunction(IntuitionBase,&LVOSetWindowTitles,var(aSetWindowTitles));
VAR(OldOpenScreen) =
SetFunction(IntuitionBase,&LVOOpenScreen,var(aOpenScreen));
}
/*
* UnSetVectors()
*
* Replace the old Intuition library vectors, but make sure that no one
* else has changed them behind our back. If they are not the same as
* what we set them to originally, then put back the ones that we found,
* and return an error status.
*/
static int UnSetVectors()
{
long NewOpenWindow;
long NewSetWindowTitles;
long NewOpenScreen;
int status = TRUE;
NewOpenWindow = SetFunction(IntuitionBase,&LVOOpenWindow,VAR(OldOpenWindow));
NewSetWindowTitles =
SetFunction(IntuitionBase,&LVOSetWindowTitles,VAR(OldSetWindowTitles));
NewOpenScreen = SetFunction(IntuitionBase,&LVOOpenScreen,VAR(OldOpenScreen));
if (NewOpenWindow != (long) var(aOpenWindow) ||
NewSetWindowTitles != (long) var(aSetWindowTitles) ||
NewOpenScreen != (long) var(aOpenScreen))
{
SetFunction(IntuitionBase,&LVOOpenWindow,NewOpenWindow);
SetFunction(IntuitionBase,&LVOSetWindowTitles,NewSetWindowTitles);
SetFunction(IntuitionBase,&LVOOpenScreen,NewOpenScreen);
status = FALSE;
}
return(status);
}
/*
* SetVariables()
*
* The IconHandlerData structure is used to allow the loading program to
* set up variables needed by the handler (like Intuitionbase, etc.). This
* keeps the handler code to a minimum. The loader retains pointers to the
* linked lists, in case it needs to free memory on behalf of the handler.
*/
void SetVariables(thePort)
struct MsgPort *thePort;
{
VAR(IntuitionBase) = IntuitionBase;
VAR(SysBase) = SysBase;
VAR(FirstDefine) = FirstDefine;
VAR(FirstProgram) = FirstProgram;
VAR(ProgramAny) = ProgramAny;
}
/*
* GetVariables()
*
* Look up the values stored in the IconHandlerData structure. The
* Intuition library already was opened, and we will need to close it.
* The data in the linked lists may need to be freed.
*/
void GetVariables(thePort)
struct MsgPort *thePort;
{
IconHandlerData = (struct IconHandlerInfo *)thePort;
IntuitionBase = VAR(IntuitionBase);
FirstDefine = VAR(FirstDefine);
FirstProgram = VAR(FirstProgram);
ProgramAny = VAR(ProgramAny);
Segment = var(Segment);
}
/*
* SetIcons()
*
* For each window in the list of initial windows
* Get the autoiconify flag and remove it from the icon
* Set the given window to the specified icon
* If autoiconify was set
* Iconify the window and replace the autoiconify flag
*/
static void SetIcons(InitIcon,i)
struct NeedsIcon InitIcon[MAXICONS];
short i;
{
ULONG AutoIconify;
while (i--)
{
AutoIconify = InitIcon[i].Icon->Flags & WI_AUTOICONIFY;
InitIcon[i].Icon->Flags -= AutoIconify;
wSetIcon(InitIcon[i].Window,InitIcon[i].Icon);
if (AutoIconify)
{
wIconify(InitIcon[i].Window);
InitIcon[i].Icon->Flags |= AutoIconify;
}
}
}
/*
* SetInitialIcons()
*
* Forbid() so that nothing happens while we're looking at the lists
* Start with the first screen of intutition
* While there are more screens to check
* Start with the screen's first window
* While there are more windows to check
* Get the port used by the window
* If it has a port, and the port has a signal-taks, and the port's
* action is to signal the task, then get the name of the process
* that owns the port
* Otherwise
* Use the name [NULL]
* Find the program/screen/window combination in the list
* If it was found and ther eis more room in the list
* Record the window and icon so we can add it later
* Move on to the next window
* Move on to the next screen
* Permit
* If there were icons to add, then add them (we postpone the adding
* until now since it requires wIconify-Handler to be running, but
* we wanted to stay in the Forbid() state without interuption).
*/
static void SetInitialIcons()
{
struct NeedsIcon InitIcon[MAXICONS];
short i = 0;
struct Screen *theScreen;
struct Window *theWindow;
struct MsgPort *thePort;
char Program[MAXNAME];
ICONWINDOW *theIcon;
Forbid();
theScreen = IntuitionBase->FirstScreen;
while (theScreen)
{
theWindow = theScreen->FirstWindow;
while (theWindow)
{
thePort = theWindow->UserPort;
if (thePort && thePort->mp_SigTask != NULL &&
(thePort->mp_Flags & PF_ACTION) == PA_SIGNAL)
VAR(GetProgramName)(Program,thePort->mp_SigTask);
else
strcpy(Program,"[NULL]");
theIcon = VAR(FindIcon)(Program,theScreen,theWindow->Title);
if (theIcon && i<MAXICONS)
{
InitIcon[i].Window = theWindow;
InitIcon[i].Icon = &(theIcon->Icon);
i++;
}
theWindow = theWindow->NextWindow;
}
theScreen = theScreen->NextScreen;
}
Permit();
if (i) SetIcons(InitIcon,i);
}
/*
* StillRunning()
*
* If we have an error message to print
* Print it and indicate that the handler is still active
* Clear the lists and other variables so that they are not freed during exit
*/
static void StillRunning(s)
char *s;
{
if (s)
{
printf(s);
printf("\n%s not removed\n",program);
}
ProgramAny = NULL;
FirstProgram = NULL;
FirstDefine = NULL;
IntuitionBase = NULL;
Segment = NULL;
}
/*
* InstallHandler()
*
* If there are too many arguments, exit with the USAGE message
* Load the handler
* If an initialization file was specified, read it
* Otherwise try to read the default initialization file
* If a program was specified in the init file
* If wIconify is running
* If wIconSetter is NOT already running
* Add the wIconSetter port to the system list so we can find it later
* Set the variables needed by the handler
* Trap the Intuition library vectors used by the handler
* Check if any existing windows need icons
* Let the user know that wIconSetter is installed
* Exit without freeing memory used by the handler
* Otherwise report an appropriate message
*/
static void InstallHandler(argc,argv)
int argc;
char **argv;
{
struct MsgPort *NamedPort;
if (argc > 2) DoExit("Usage: '%s'",USAGE);
LoadHandler(&NamedPort);
if (argc == 2)
ReadInitFile(argv[1],NULL);
else
ReadInitFile(INITFILE1,INITFILE2);
if (FirstProgram || ProgramAny)
{
if (wIconifyActive())
{
if (FindPort(PORTNAME) == NULL)
{
AddPort(NamedPort);
SetVariables(NamedPort);
SetVectors();
SetInitialIcons();
printf("%s v%d.%d.%d Installed\n",program,
var(MajVers),var(MinVers),LOADVERS);
StillRunning(NULL);
} else printf("Attempt to re-install %s!\n",program);
} else printf("wIconify not running or incompatible version\n");
} else printf("No icons specified in initialization file\n");
}
/*
* RemoveHandler()
*
* Retrieve the variables that the loader set up initially
* If the versions don't match, report an error
* Otherwise
* If we can remove the SetFunction() traps
* If wIconify is still active
* Put back the trapped vectors
* Inform the user that we can't exit (wIconify amy still be using
* the icons that we have set up)
* Otherwise
* Remove the port from the system list
* Let the user know we've been deactivated
* Otherwise report an error
*/
static void RemoveHandler(NamedPort)
struct MsgPort *NamedPort;
{
GetVariables(NamedPort);
if (var(MinLoadVers) > LOADVERS || var(MajVers) < MINHMAJVERS ||
(var(MajVers) == MINHMAJVERS && var(MinVers) < MINHMINVERS))
StillRunning("Loader version mismatch");
else
{
if (UnSetVectors())
{
if (wIconifyActive())
{
SetVectors();
StillRunning("Can't cancel wIconSetter while wIconify is active");
} else {
RemPort(NamedPort);
printf("%s removed\n",program);
}
} else StillRunning("SetFunction vectors have been changed!");
}
}
/*
* main()
*
* Open the necessary libraries
* Look in the system list to see if wIconSetter is already running
* If not running, try to install the handler,
* Otherwise try to cancel the handler
*/
void main(argc,argv)
int argc;
char **argv;
{
struct MsgPort *NamedPort;
CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
CheckLibOpen(&GfxBase,"graphics.library",GRAPHICS_REV);
NamedPort = FindPort(PORTNAME);
if (NamedPort == NULL)
InstallHandler(argc,argv);
else
RemoveHandler(NamedPort);
DoExit(NULL);
}